package BLC

import (
	"bytes"
	"crypto/sha256"
	"encoding/gob"
	"log"
	"time"
)

type Block struct {
	TimeStamp     int64  //区块时间戳
	Height        int64  // 区块链高度(索引,号码),代表区块链的长度
	PrevBlockHash []byte //前一个区块的哈希
	Hash          []byte //自己的哈希值
	TXs           []*Transaction
	Nonce         int64 //生成工作量证明的 (POW) hash
	//Data          []byte //交易数据
}

//创建区块
func NewBlock(height int64, prevBlockHash []byte, txs []*Transaction) *Block {
	block := &Block{
		TimeStamp:     time.Now().Unix(),
		Height:        height,
		PrevBlockHash: prevBlockHash,
		TXs:           txs,
	}

	//block.SetHash()

	pow := NewProofOfWork(block)

	//工作量证明
	block.Hash, block.Nonce = pow.Run()
	return block
}

//当前信息计算区块
//func (self *Block) SetHash() {
//
//	//int64 转换成[]byte
//	heightByte := IntToHex(self.Height)
//	timeStamp := IntToHex(self.TimeStamp)
//
//	//拼接所有属性,进行哈希
//	blockBytes := bytes.Join([][]byte{
//		heightByte,
//		timeStamp,
//		self.PrevBlockHash,
//		self.Data,
//	}, []byte{})
//
//	hash := sha256.Sum256(blockBytes)
//	self.Hash = hash[:]
//}

//生成创世区块
func CreateGenesisBlock(txs []*Transaction) *Block {
	block := NewBlock(1, nil, txs)
	return block
}

//序列化 将区块结构转化成[]byte
func Serialize(block *Block) []byte {
	var result bytes.Buffer
	encoder := gob.NewEncoder(&result) //新建一个encode

	err := encoder.Encode(block)
	if err != nil {
		log.Panicf("序列化块到字节失败: %v\n", err)
	}
	return result.Bytes()
}

//反序列化
func DeserializeBlocker(blockByte []byte) *Block {
	var block Block
	decode := gob.NewDecoder(bytes.NewReader(blockByte))
	err := decode.Decode(&block)
	if err != nil {
		log.Panicf("反序列化 bype to  block 失败: %v\n", err)
	}
	return &block
}

//把区块中所有交易转换成hash []byte
func (self *Block) HashTransaction() []byte {
	var txHashs [][]byte
	for _, tx := range self.TXs {
		txHashs = append(txHashs, tx.TxHash)
	}
	txHash := sha256.Sum256(bytes.Join(txHashs, []byte{}))
	return txHash[:]
}
